/**
 * Copyright (c) 2014-2015, Suredy technology Co., Ltd. All rights reserved.
 * @author ZhangMaoren 
 * @since 2015年6月15日
 * @version 0.1
 */
package com.suredy.resource.ctrl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.suredy.Constants;
import com.suredy.core.ctrl.BaseCtrl;
import com.suredy.core.mvc.model.MessageModel;
import com.suredy.core.mvc.model.Tree;
import com.suredy.core.mvc.model.TreeMenu;
import com.suredy.resource.entity.MenuEntity;
import com.suredy.resource.entity.ResourceEntity;
import com.suredy.resource.entity.SegmentEntity;
import com.suredy.resource.model.ResourceType;
import com.suredy.resource.service.MenuSrv;
import com.suredy.resource.service.ResourceSrv;
import com.suredy.resource.service.SegmentSrv;
import com.suredy.security.entity.Role2PermissionEntity;
import com.suredy.security.entity.User2PermissionEntity;
import com.suredy.security.model.User;
import com.suredy.security.service.Role2PermissionSrv;
import com.suredy.security.service.User2PermissionSrv;
import com.suredy.security.service.UserSrv;


/**
 * @author ZhangMaoren
 *
 */
@Controller
@RequestMapping(value="/config")
public class ResourceCtrl extends BaseCtrl{
	private final static Logger log = LoggerFactory.getLogger(ResourceCtrl.class);
	
	@Autowired
	private MenuSrv menuSrv;
	
	@Autowired
	private SegmentSrv segmentSrv;
	
	@Autowired 
	ResourceSrv resourceSrv;
	
	@Autowired
	private Role2PermissionSrv role2permissionSrv;
	
	@Autowired
	private User2PermissionSrv user2permissionSrv;
	
	@Autowired
	private UserSrv userSrv;
	
	@RequestMapping({"menu/user"})
	@ResponseBody
	public Object UserMenuTree(HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute(Constants.SESSION_LOGIN_USER);
		// not login
		if (user == null) {
			log.info("Session timeout or User didn't login.");
			return MessageModel.createErrorMessage("用户未登录或会话超时", null);
		}
		// 当前用户可访问的安全资源点
		List<String> userSecurityResources = this.userSrv.getPermissions(user.getUniqueCode());
		//TODO 读取数据库内的资源配置或者从Session读取，二选一
		//Set<String> permissions = this.userSrv.getPermissions(user.getUniqueCode());
		// 全部菜单相关的安全资源点
		List<ResourceEntity> menues = this.resourceSrv.getAll(ResourceType.Menu);
		// 已授权用户访问的菜单相关安全资源点
		Set<String> allowedMenues = new HashSet<String>();
		if(menues!=null)
		for (ResourceEntity menu : menues) {
			if (userSecurityResources.contains(menu.getUri())) {
				allowedMenues.add(menu.getId());
			}
		}
		
		List<TreeMenu> tree = this.menuSrv.getMenuTree(null, allowedMenues);
		if (tree == null || tree.isEmpty()) {
			return null;
		} 
		return tree;
	}
	
	
	
	@RequestMapping("menu/tree")
	@ResponseBody
	public Object ManagerMenuTree() {
		List<Tree> tree = this.menuSrv.getMenuTree(null);
		return tree == null ? null : tree;
	}
	
	@RequestMapping(value = "menu/manager")
	public ModelAndView MenuManager() {
		ModelAndView view = new ModelAndView("/config/resource/menu-manager");
		return view;
	}
	
	@RequestMapping(value = "menu/edit")
	public ModelAndView editMenu(String id, String parentId) {
		ModelAndView view = new ModelAndView("/config/resource/menu-form");
		MenuEntity data; 
		if (StringUtils.isEmpty(id)) {
			data = new MenuEntity();
			data.setCollapse(false); //默认收拢
			data.setActive(false);
			data.setParent(new MenuEntity());
			data.getParent().setId(parentId);
		} else {
			data = this.menuSrv.get(id);
		}
		view.addObject("data", data);
		return view;
	}
	
	@RequestMapping("menu/save")
	@ResponseBody
	public Object updateMenu(HttpServletRequest request) {
		String id = request.getParameter("id");
		String parent = request.getParameter("parent");
		String text = request.getParameter("text");
		String url = request.getParameter("url");
		String sort = request.getParameter("sort");
		String icon = request.getParameter("icon");
		String active = request.getParameter("active");
		String collapse = request.getParameter("collapse");
		if ( StringUtils.isEmpty(text)) {
			log.info("Parameter String[text] is blank.");
			return MessageModel.createErrorMessage("参数不足, 菜单名称必须填写", null);
		}
		if (StringUtils.isEmpty(id)) {
			Date date = new Date();
			ResourceEntity resource = new ResourceEntity();
			resource.setCreateTime(date);
			resource.setLastModifiedTime(date);
			resource.setName(text);
			resource.setType(ResourceType.Menu.getType());
			resource.setUri(UUID.randomUUID().toString());
			MenuEntity menu = new MenuEntity();
			menu.setUrl(StringUtils.isEmpty(url) ? null : url);
			menu.setText(text);
			menu.setSort(StringUtils.isEmpty(sort) ? 0 : Integer.parseInt(sort));
			menu.setIcon(StringUtils.isEmpty(icon) ? null : icon);
			menu.setActive(Boolean.valueOf(active));
			menu.setCollapse(Boolean.valueOf(collapse));
			menu.setResource(resource);
			if (!StringUtils.isEmpty(parent)) {
				menu.setParent(new MenuEntity());
				menu.getParent().setId(parent);
			}
			this.menuSrv.save(menu);
		} else {
			MenuEntity menu = this.menuSrv.get(id);
			if (menu == null) {
				return MessageModel.createErrorMessage("参数错误, 未找到与ID对应的菜单信息", null);
			}
			
			menu.setUrl(StringUtils.isEmpty(url) ? null : url);
			menu.setText(text);
			menu.setSort(StringUtils.isEmpty(sort) ? 0 : Integer.parseInt(sort));
			menu.setIcon(StringUtils.isEmpty(icon) ? null : icon);
			menu.setActive(Boolean.valueOf(active));
			menu.setCollapse(Boolean.valueOf(collapse));
	
			if (!StringUtils.isEmpty(parent)) {
				if (! parent.equals(id)) {
					menu.setParent(new MenuEntity());
					menu.getParent().setId(parent);
				}
			} else {
				menu.setParent(null);
			}
			ResourceEntity resource = menu.getResource();
			resource.setName(text);
			if (!StringUtils.isEmpty(url)) {
				resource.setUri(url);
			}
			menu.setResource(resource);
			this.menuSrv.update(menu);
		}
		return MessageModel.createSuccessMessage(null, null);
	}	
	
	
	@RequestMapping("menu/delete")
	@ResponseBody
	public Object MenuDelete(String menuId) {
		if (StringUtils.isEmpty(menuId)) {
			return MessageModel.createErrorMessage("无效的菜单ID！", null);
		}

		MenuEntity menu = this.menuSrv.get(menuId);

		if (menu == null) {
			return MessageModel.createErrorMessage("未找到与ID对应的菜单信息！", null);
		}

		try {
			this.menuSrv.delete(menu);
		} catch (Exception e) {
			return MessageModel.createErrorMessage("删除不成功,菜单信息映射错误！", null);
		}

		return MessageModel.createSuccessMessage(null, null);
	}
	
	@RequestMapping({"segment/user"})
	@ResponseBody
	public Object UserSegments(HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute(Constants.SESSION_LOGIN_USER);
		// not login
		if (user == null) {
			log.info("Session timeout or User didn't login.");
			return MessageModel.createErrorMessage("用户未登录或会话超时", null);
		}
		// 当前用户可访问的安全资源点
		List<String> userSecurityResources = this.userSrv.getPermissions(user.getUniqueCode());
		// TODO 读取数据库内的资源配置或者从Session读取，二选一
		// Set<String> permissions = this.userSrv.getPermissions(user.getUniqueCode());
		// 全部页面片段相关的安全资源点
		List<ResourceEntity> segments = this.resourceSrv.getAll(ResourceType.Segment);
		// 已授权用户访问的菜单相关安全资源点
		List<String> allowedResources = new ArrayList<String>();
		for (ResourceEntity segment : segments) {
			if (userSecurityResources.contains(segment.getUri())) {
				allowedResources.add(segment.getUri());
			}
		}
		return allowedResources;
	}


	@RequestMapping(value = "segment/manager")
	public ModelAndView segmentManager() {
		ModelAndView view = new ModelAndView("/config/resource/segment-manager");
		List<SegmentEntity> data = this.segmentSrv.getAll();
		view.addObject("data", data);
		return view;
	}

	@RequestMapping(value = "segment/form")
	public ModelAndView editSegment(String id) {
		ModelAndView view = new ModelAndView("/config/resource/segment-form");
		SegmentEntity data;
		if (StringUtils.isEmpty(id)) {
			data = new SegmentEntity();
		} else {
			data = this.segmentSrv.get(id);
		}
		view.addObject("data", data);
		return view;
	}

	@RequestMapping("segment/save")
	@ResponseBody
	public Object segmentUpdate(HttpServletRequest request) {
		String name = request.getParameter("name");
		String uri = request.getParameter("uri");
		String sort = request.getParameter("sort");
		String id = request.getParameter("id");
		if (StringUtils.isEmpty(name) || StringUtils.isEmpty(uri)) {
			log.info("Parameter String[name|uri] is blank.");
			return MessageModel.createErrorMessage("参数不足, 名称和资源标识必须填写", null);
		}

		Date date = new Date();

		if (StringUtils.isEmpty(id)) {
			ResourceEntity resource = new ResourceEntity();
			resource.setCreateTime(date);
			resource.setLastModifiedTime(date);
			resource.setName(name);
			resource.setType(ResourceType.Segment.getType());
			resource.setUri(uri);
			SegmentEntity entity = new SegmentEntity();
			entity.setName(name);
			entity.setSort(StringUtils.isEmpty(sort) ? 0 : Integer.parseInt(sort));
			entity.setUri(uri);
			entity.setResource(resource);
			this.segmentSrv.save(entity);
		} else {
			SegmentEntity entity = this.segmentSrv.get(id);
			entity.setName(name);
			entity.setSort(StringUtils.isEmpty(sort) ? 0 : Integer.parseInt(sort));
			entity.setUri(uri);
			ResourceEntity resource = entity.getResource();
			resource.setName(name);
			resource.setUri(uri);
			entity.setResource(resource);
			this.segmentSrv.update(entity);
		}
		return MessageModel.createSuccessMessage(null, null);
	}


	@RequestMapping("segment/delete")
	@ResponseBody
	public Object doDelete(String id) {
		if (StringUtils.isEmpty(id)) {
			return MessageModel.createErrorMessage("无效的资源ID！", null);
		}

		SegmentEntity entity = this.segmentSrv.get(id);

		if (entity == null) {
			return MessageModel.createErrorMessage("未找到与ID对应的资源信息！", null);
		}

		try {
			this.segmentSrv.delete(entity);
		} catch (Exception e) {
			return MessageModel.createErrorMessage("删除不成功,控制资源信息映射错误！", null);
		}

		return MessageModel.createSuccessMessage(null, null);
	}
	
	@RequestMapping("resource/user")
	@ResponseBody
	public Object ResourceUser(String userId) {
		Tree root = new Tree();
		root.setText("安全资源");
		root.setCollapse(false);
		root.setChildren(new ArrayList<Tree>());
		
		List<User2PermissionEntity> userPermissions = this.user2permissionSrv.getByUser(userId);
		List<String> resources = new ArrayList<String>();
		for (User2PermissionEntity u2p : userPermissions) {
			resources.add(u2p.getPermission().getResource().getId());
		}
		Tree menuTree = new Tree();
		menuTree.setText("菜单类");
		menuTree.setCollapse(false);
		List<Tree> menuChildren = this.menuSrv.getMenuTree(null, resources);
		if (menuChildren != null) {
			menuTree.setChildren(new ArrayList<Tree>());
			menuTree.getChildren().addAll(menuChildren);
		}
		
		Tree segments = new Tree();
		List<Tree> segmentTree = new ArrayList<Tree>();
		List<SegmentEntity> segmentsData = this.segmentSrv.getAll();
		if (segmentsData != null) {
			for (SegmentEntity segment : segmentsData) {
				Tree temp = new Tree();
				temp.setText(segment.getName());
				temp.setData(segment.toVO());
				if (resources.contains(segment.getResource().getId())) {
					temp.setChecked(true);
				}
				segmentTree.add(temp);
			}
		}
		segments.setText("单点控制");
		segments.setCollapse(true);
		segments.setChildren(new ArrayList<Tree>());
		segments.getChildren().addAll(segmentTree);
		
		root.getChildren().add(menuTree);
		root.getChildren().add(segments);
		return root;

	}
	
	@RequestMapping("resource/role")
	@ResponseBody
	public Object ResourceRole(String roleId) {
		Tree root = new Tree();
		root.setText("安全资源");
		root.setCollapse(false);
		root.setChildren(new ArrayList<Tree>());
		List<Role2PermissionEntity> rolePermissions = this.role2permissionSrv.getByRole(roleId);
		List<String> resources = new ArrayList<String>();
		for (Role2PermissionEntity r2p : rolePermissions) {
			resources.add(r2p.getPermission().getResource().getId());
		}
		Tree menuTree = new Tree();
		menuTree.setText("菜单类");
		menuTree.setCollapse(false);
		List<Tree> menuChildren = this.menuSrv.getMenuTree(null, resources);
		if (menuChildren != null) {
			menuTree.setChildren(new ArrayList<Tree>());
			menuTree.getChildren().addAll(menuChildren);
		}
		
		Tree segments = new Tree();
		List<Tree> segmentTree = new ArrayList<Tree>();
		List<SegmentEntity> segmentsData = this.segmentSrv.getAll();
		if (segmentsData != null) {
			for (SegmentEntity segment : segmentsData) {
				Tree temp = new Tree();
				temp.setText(segment.getName());
				temp.setData(segment.toVO());
				if (resources.contains(segment.getResource().getId())) {
					temp.setChecked(true);
				}
				segmentTree.add(temp);
			}
		}
		segments.setText("单点控制");
		segments.setCollapse(false);
		segments.setChildren(new ArrayList<Tree>());
		segments.getChildren().addAll(segmentTree);
		
		root.getChildren().add(menuTree);
		root.getChildren().add(segments);
		return root;

	}
	
	@RequestMapping("resource/tree")
	@ResponseBody
	public Object ResourceTree() {
		Tree root = new Tree();
		root.setText("安全资源");
		root.setCollapse(false);
		root.setChildren(new ArrayList<Tree>());
		
		Tree menus = new Tree();
		menus.setText("菜单类");
		menus.setCollapse(false);
		List<Tree> menuChildren = this.menuSrv.getMenuTree(null);
		if (menuChildren != null) {
			menus.setChildren(new ArrayList<Tree>());
			menus.getChildren().addAll(menuChildren);
		}
		
		Tree segments = new Tree();
		List<Tree> segmentTree = new ArrayList<Tree>();
		List<SegmentEntity> segmentsData = this.segmentSrv.getAll();
		if (segmentsData != null) {
			for (SegmentEntity segment : segmentsData) {
				Tree temp = new Tree();
				temp.setText(segment.getName());
				temp.setData(segment.toVO());
				segmentTree.add(temp);
			}
		}
		segments.setText("单点控制");
		segments.setCollapse(true);
		segments.setChildren(new ArrayList<Tree>());
		segments.getChildren().addAll(segmentTree);
		
		
		root.getChildren().add(menus);
		root.getChildren().add(segments);
		return root;

	}
	
	
}
